using System.Text;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace HEFramework
{
    internal class DataTableTemplate : ScriptableObject
    {
        /// <summary>
        ///  代码模板
        /// </summary>
        public string[] CodeTemplate;

        /// <summary>
        ///  属性定义模板propertieseDefine
        /// </summary>
        public string[] PropertieseDefineTemplate;

        /// <summary>
        ///  属性解析模板propertieseParse
        /// </summary>
        public string PropertieseParseTemplate;

        /// <summary>
        ///  属性解析时值
        /// </summary>
        public string PropertyParseValue;

        /// <summary>
        ///  属性解析时值(FromKey)
        /// </summary>
        public string PropertyParseValueFromKey;

        /// <summary>
        ///  导出代码文件名字
        /// </summary>
        public string CodeFileName;

        /// <summary>
        ///  导出数据文件名字
        /// </summary>
        public string DataFileName;

        /// <summary>
        ///  多语言导出注释
        /// </summary>
        public string LangOutputNote;

        /// <summary>
        ///  多语言导出项
        /// </summary>
        public string LangOutputItem;

        /// <summary>
        ///  多语言导出Key
        /// </summary>
        public string LangOutputKey;

        /// <summary>
        ///  多语言导出文件开头
        /// </summary>
        public string[] LangOutputStartWith;

        /// <summary>
        ///  多语言导出文件结尾
        /// </summary>
        public string[] LangOutputEndWith;


        private string CodeTemplateStr;
        private string PropertieseDefineTemplateStr;
        private string LangOutputStartWithStr;
        private string LangOutputEndWithStr;
        

        private static DataTableTemplate inst;
        public static DataTableTemplate Inst => inst;

        public static void Load(string _path)
        {
            inst = (DataTableTemplate)AssetDatabase.LoadAssetAtPath(_path, typeof(DataTableTemplate));

            inst.CodeTemplateStr = string.Join("\n", inst.CodeTemplate);
            inst.PropertieseDefineTemplateStr = string.Join("\n", inst.PropertieseDefineTemplate);
            inst.LangOutputStartWithStr = string.Join("\n", inst.LangOutputStartWith);
            inst.LangOutputEndWithStr = string.Join("\n", inst.LangOutputEndWith);
        }

        public static void Create(string _path)
        {
            DataTableTemplate dataTableTemplate = ScriptableObject.CreateInstance<DataTableTemplate>();
            dataTableTemplate.CodeTemplate = new string[]
            {
                "using System.Collections.Generic;",
                "using UnityEngine;",
                "",
                "namespace HEFramework",
                "{",
                "    /// <summary>",
                "    /// {sheetName} data,{fileName}.xlsx",
                "    /// </summary>",
                "    public class DR{sheetName}:IData",
                "    {",
                "        ",
                "{propertieseDefine}",
                "        ",
                "        public void ParseDataRow(string input)",
                "        {",
                "            string[] text = input.Split('\t');",
                "            int index = 0;",
                "        ",
                "{propertieseParse}",
                "        }",
                "        ",
                "        private void AvoidJIT()",
                "        {",
                "            new Dictionary<int, DR{sheetName}>();",
                "        }",
                "    }",
                "}",
            };
            dataTableTemplate.PropertieseDefineTemplate = new string[]
            {
                "        /// <summary>",
                "        /// {note}  {setting}",
                "        /// </summary>",
                "        public {type} {name} { get; protected set; }",
                "",
            };

            dataTableTemplate.PropertieseParseTemplate =
                "            {name} = {parse};\n";
            dataTableTemplate.PropertyParseValue =
                "text[index++]";
            dataTableTemplate.PropertyParseValueFromKey =
                "DataTableExtension.GetStringFromKey(text[index++])";
            dataTableTemplate.CodeFileName =
                "DR{sheetName}.cs";
            dataTableTemplate.DataFileName =
                "{sheetName}.txt";
            dataTableTemplate.LangOutputNote =
                "  <!-- file = {0} sheet = {1} name = {2} -->";
            dataTableTemplate.LangOutputItem =
                "    <String Key=\"{0}\" Value=\"{1}\" />";
            dataTableTemplate.LangOutputKey =
                "{0}_{1}_{2}";
            dataTableTemplate.LangOutputStartWith = new string[]
            {
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
                "<Dictionaries>",
                "  <Dictionary Language = \"ChineseSimplified\" >",
            };
            dataTableTemplate.LangOutputEndWith = new string[]
            {
                "</Dictionary>",
                "</Dictionaries>",
            };
            AssetDatabase.CreateAsset(dataTableTemplate, _path);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        public string GetCodeFilePath(string _sheetName)
        {
            return DataTableSettingScriptableObject.Instance.SaveCodePath + "\\" + CodeFileName.Replace("{sheetName}", _sheetName);
        }

        public string GetDataFilePath(string _sheetName)
        {
            return DataTableSettingScriptableObject.Instance.SaveDataPath + "\\" + DataFileName.Replace("{sheetName}", _sheetName);
        }

        public StringBuilder GetCodeText(string _fileName, string _sheetName, List<Property> _properties)
        {
            StringBuilder propertieseDefineText = new StringBuilder();
            foreach (var property in _properties)
            {
                StringBuilder template = new StringBuilder(PropertieseDefineTemplateStr);
                template.Replace("{type}", property.Type);
                template.Replace("{name}", property.Name);
                template.Replace("{note}", property.Note);
                template.Replace("{setting}", property.Setting);
                propertieseDefineText.Append(template);
            }

            StringBuilder propertieseParseText = new StringBuilder();
            foreach (var property in _properties)
            {
                StringBuilder template = new StringBuilder(PropertieseParseTemplate);
                template.Replace("{name}", property.Name);
                string parseFunc = property.IsArray ? property.GetArrParseFunc() : property.GetParseFunc();
                string parseValue = property.IsOutputKey ? PropertyParseValueFromKey : PropertyParseValue;
                if (parseFunc == "")
                {
                    template.Replace("{parse}", parseValue);
                }
                else
                {
                    template.Replace("{parse}", parseFunc + "(" + parseValue + ")");
                }

                propertieseParseText.Append(template);
            }

            StringBuilder codeText = new StringBuilder(CodeTemplateStr);
            codeText.Replace("{propertieseDefine}", propertieseDefineText.ToString());
            codeText.Replace("{propertieseParse}", propertieseParseText.ToString());
            codeText.Replace("{fileName}", _fileName.Replace(".xlsx", "")); //去掉后缀
            codeText.Replace("{sheetName}", _sheetName);
            return codeText;
        }

        public void AppendLangOutputNote(StringBuilder _resultAppend, string _fileName, string _sheetName, string _propertyName)
        {
            _resultAppend.Append(string.Format(LangOutputNote, _fileName, _sheetName, _propertyName));
        }

        public void AppendLangOutputItem(StringBuilder _resultAppend, string _key, string _value)
        {
            _resultAppend.Append(string.Format(LangOutputItem, _key, XmlUtils.EncodeString(_value, true)));
        }

        public string GetLangOutputKey(string _sheetName, string _propertyName, string _id)
        {
            return string.Format(LangOutputKey, _sheetName, _propertyName, _id);
        }

        public string GetLangOutputStartWith()
        {
            return LangOutputStartWithStr;
        }

        public string GetLangOutputEndWith()
        {
            return LangOutputEndWithStr;
        }
    }
}